package com.github.ompc.carrying.server.service.impl;

import com.github.ompc.carrying.common.domain.Row;
import com.github.ompc.carrying.common.exception.CarryingException;
import com.github.ompc.carrying.common.service.CarryingService;
import com.github.ompc.carrying.server.cache.RowCache;
import com.github.ompc.carrying.server.dao.RowDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

import static java.lang.System.arraycopy;

/**
 * 搬运服务实现
 * Created by vlinux on 14-9-1.
 */
public class CarryingServiceImpl implements CarryingService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private RowDao rowDao;
    private RowCache rowCache;

    @Override
    public Row carry(int token, boolean isReTry) throws CarryingException {
        try {

            Row row;
            if( isReTry ) {
                row = rowCache.getRow(token);
                if( null != row ) {
                    return row;
                }
            }

            // 没命中缓存或第一次
            row = rowDao.getRow();
            if( null != row ) {

                // 处理业务
                row.setData(process(row.getData()));

                // 推入缓存
                putCache(token, row);

            }
            return row;
        } catch (IOException e) {
            logger.warn("CarryingServiceImpl@carry error, token={};isReTry={};",
                    new Object[]{token, isReTry}, e);
            throw new CarryingException("Carry data error!.",e);
        }
    }

    /**
     * 从size/3字符开始去掉size/3个字符，除法向下取整
     * @param data 原数据
     * @return 处理后数据
     */
    private static byte[] process(byte[] data) {
        final int size = data.length;
        final int sub = size / 3;
        final byte[] newData = new byte[size - sub];
        arraycopy(data, 0, newData, 0, sub);
        arraycopy(data, sub+sub, newData, sub, newData.length-sub);
        return newData;
    }

    /**
     * 推入缓存
     * @param token
     * @param row
     */
    private void putCache(int token, Row row) {
        rowCache.putRow(token, row);
    }

    public void setRowDao(RowDao rowDao) {
        this.rowDao = rowDao;
    }

    public void setRowCache(RowCache rowCache) {
        this.rowCache = rowCache;
    }
}
